using AutoMapper;
using B.S.NewMedical.Api.Read.Application.Command.Doctor;
using B.S.NewMedical.Api.Read.DTOS.Doctor;
using B.S.NewMedical.Domain.Doctor;
using B.S.NewMedical.Domain.Hospital;
using B.S.NewMedical.Domain.Appointment;
using B.S.NewMedical.ErrorCode;
using B.S.NewMedical.Infrastructure.Interface;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace B.S.NewMedical.Api.Read.Application.Handler.Doctor
{
    public class GetPrescriptionApplicationDetailHandler : IRequestHandler<GetPrescriptionApplicationDetailCommand, ApiResult<PrescriptionApplicationDetailDto>>
    {
        private readonly IBaseRepository<PrescriptionApplicationModel> _prescriptionApplicationRepository;
        private readonly IBaseRepository<PrescriptionDetailModel> _prescriptionDetailRepository;
        private readonly IBaseRepository<HospitalModel> _hospitalRepository;
        private readonly IBaseRepository<PatientModel> _patientRepository;
        private readonly IBaseRepository<MedicalCard> _medicalCardRepository;
        private readonly IBaseRepository<DrugInfoModel> _drugRepository;
        private readonly IBaseRepository<CheckupItemModel> _checkupItemRepository;
        private readonly IBaseRepository<TestItemModel> _testItemRepository;
        private readonly ILogger<GetPrescriptionApplicationDetailHandler> _logger;
        private readonly IMapper _mapper;

        public GetPrescriptionApplicationDetailHandler(
            IBaseRepository<PrescriptionApplicationModel> prescriptionApplicationRepository,
            IBaseRepository<PrescriptionDetailModel> prescriptionDetailRepository,
            IBaseRepository<HospitalModel> hospitalRepository,
            IBaseRepository<PatientModel> patientRepository,
            IBaseRepository<MedicalCard> medicalCardRepository,
            IBaseRepository<DrugInfoModel> drugRepository,
            IBaseRepository<CheckupItemModel> checkupItemRepository,
            IBaseRepository<TestItemModel> testItemRepository,
            ILogger<GetPrescriptionApplicationDetailHandler> logger,
            IMapper mapper)
        {
            _prescriptionApplicationRepository = prescriptionApplicationRepository;
            _prescriptionDetailRepository = prescriptionDetailRepository;
            _hospitalRepository = hospitalRepository;
            _patientRepository = patientRepository;
            _medicalCardRepository = medicalCardRepository;
            _drugRepository = drugRepository;
            _checkupItemRepository = checkupItemRepository;
            _testItemRepository = testItemRepository;
            _logger = logger;
            _mapper = mapper;
        }

        public async Task<ApiResult<PrescriptionApplicationDetailDto>> Handle(GetPrescriptionApplicationDetailCommand request, CancellationToken cancellationToken)
        {
            try
            {
                _logger.LogInformation("开始获取开单申请详情，申请ID：{ApplicationId}", request.ApplicationId);

                // 查询开单申请
                var application = await _prescriptionApplicationRepository.GetAll()
                    .FirstOrDefaultAsync(p => p.Id == request.ApplicationId && !p.IsDeleted, cancellationToken);

                if (application == null)
                {
                    return new ApiResult<PrescriptionApplicationDetailDto>
                    {
                        Code = ApiEnum.Fail,
                        Msg = "开单申请不存在"
                    };
                }

                // 查询医院信息
                var hospital = await _hospitalRepository.GetValue(application.HospitalId);
                
                // 查询患者信息
                var patient = await _patientRepository.GetValue(application.PatientId);
                
                // 查询患者的医疗卡信息
                var medicalCard = await _medicalCardRepository.GetAll()
                    .FirstOrDefaultAsync(m => m.Patient_id == application.PatientId && !m.IsDeleted, cancellationToken);

                // 查询开单项目详情
                var details = await _prescriptionDetailRepository.GetAll()
                    .Where(d => d.ApplicationId == request.ApplicationId && !d.IsDeleted)
                    .ToListAsync(cancellationToken);

                // 获取药品、检查项目、检验项目的ID集合
                var drugIds = details.Where(d => d.ItemType == 1).Select(d => d.ItemId).Distinct().ToList();
                var checkupIds = details.Where(d => d.ItemType == 2).Select(d => d.ItemId).Distinct().ToList();
                var testIds = details.Where(d => d.ItemType == 3).Select(d => d.ItemId).Distinct().ToList();

                // 查询对应的基础数据
                var drugs = await _drugRepository.GetAll()
                    .Where(d => drugIds.Contains(d.Id) && !d.IsDeleted)
                    .ToDictionaryAsync(d => d.Id, d => d, cancellationToken);

                var checkupItems = await _checkupItemRepository.GetAll()
                    .Where(c => checkupIds.Contains(c.Id) && !c.IsDeleted)
                    .ToDictionaryAsync(c => c.Id, c => c, cancellationToken);

                var testItems = await _testItemRepository.GetAll()
                    .Where(t => testIds.Contains(t.Id) && !t.IsDeleted)
                    .ToDictionaryAsync(t => t.Id, t => t, cancellationToken);

                // 构建详情DTO
                var result = new PrescriptionApplicationDetailDto
                {
                    Id = application.Id,
                    PrescriptionInfo = new PrescriptionInfoDto
                    {
                        HospitalName = hospital?.HospitalName ?? "未知医院",
                        PatientName = patient?.Name ?? "未知患者",
                        CardNo = medicalCard?.Card_no ?? "无",
                        TotalAmount = application.TotalAmount,
                        ApplicationTime = application.ApplicationTime,
                        Status = GetStatusName(application.Status)
                    },
                    Items = details.Select(d => new PrescriptionItemDto
                    {
                        Id = d.Id,
                        TypeIcon = GetTypeIcon(d.ItemType),
                        ItemName = GetItemName(d.ItemType, d.ItemId, drugs, checkupItems, testItems),
                        QuantityText = GetQuantityText(d.ItemType, d.Quantity),
                        Amount = d.Amount,
                        Tags = GetItemTags(d.ItemType, d.ItemId, drugs, checkupItems, testItems)
                    }).ToList()
                };

                return new ApiResult<PrescriptionApplicationDetailDto>
                {
                    Code = ApiEnum.Success,
                    Msg = "获取开单申请详情成功",
                    Data = result
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取开单申请详情时发生异常");
                return new ApiResult<PrescriptionApplicationDetailDto>
                {
                    Code = ApiEnum.Error,
                    Msg = "获取开单申请详情失败：" + ex.Message
                };
            }
        }

        /// <summary>
        /// 获取状态名称
        /// </summary>
        private string GetStatusName(int status)
        {
            return status switch
            {
                0 => "待审核",
                1 => "审核通过",
                2 => "审核驳回",
                3 => "已支付",
                4 => "已取消",
                _ => "未知状态"
            };
        }

        /// <summary>
        /// 获取项目类型图标
        /// </summary>
        private string GetTypeIcon(int itemType)
        {
            return itemType switch
            {
                1 => "药", // 药品
                2 => "查", // 检查
                3 => "验", // 检验
                _ => "?"
            };
        }

        /// <summary>
        /// 获取项目名称
        /// </summary>
        private string GetItemName(int itemType, int itemId, 
            Dictionary<int, DrugInfoModel> drugs, 
            Dictionary<int, CheckupItemModel> checkupItems, 
            Dictionary<int, TestItemModel> testItems)
        {
            return itemType switch
            {
                1 => drugs.TryGetValue(itemId, out var drug) ? drug.DrugName : "未知药品",
                2 => checkupItems.TryGetValue(itemId, out var checkup) ? checkup.ItemName : "未知检查项目",
                3 => testItems.TryGetValue(itemId, out var test) ? test.ItemName : "未知检验项目",
                _ => "未知项目"
            };
        }

        /// <summary>
        /// 获取数量文本
        /// </summary>
        private string GetQuantityText(int itemType, int quantity)
        {
            return itemType switch
            {
                1 => $"数量：{quantity}剂",
                2 => $"数量：{quantity}项",
                3 => $"数量：{quantity}盒",
                _ => $"数量：{quantity}"
            };
        }

        /// <summary>
        /// 获取项目标签
        /// </summary>
        private List<string> GetItemTags(int itemType, int itemId,
            Dictionary<int, DrugInfoModel> drugs,
            Dictionary<int, CheckupItemModel> checkupItems,
            Dictionary<int, TestItemModel> testItems)
        {
            var tags = new List<string>();

            switch (itemType)
            {
                case 1: // 药品
                    tags.Add("处方药");
                    if (drugs.TryGetValue(itemId, out var drug))
                    {
                        // 可以根据药品属性添加更多标签
                        if (drug.DrugName.Contains("限购"))
                        {
                            tags.Add("限购5剂");
                        }
                    }
                    break;
                case 2: // 检查
                    tags.Add("检查项目");
                    break;
                case 3: // 检验
                    tags.Add("检验项目");
                    break;
            }

            return tags;
        }
    }
} 